<template>
  <div ref="canvas"></div>
</template>

<script lang="ts" setup>
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import Stats from "three/examples/jsm/libs/stats.module";
import { GUI }  from "three/examples/jsm/libs/lil-gui.module.min.js";
import { ref, onMounted } from "vue";

// 画布
const canvas = ref<any>('');
// 场景
const scene = new THREE.Scene();
// 相机
const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(-30, 40, 30);
camera.lookAt(scene.position);
// 平面
const planeGeometry = new THREE.PlaneGeometry(60, 40, 1, 1);
const planeMaterial = new THREE.MeshLambertMaterial({
  color: 0xffffff,
  side: THREE.DoubleSide,
});
const plane = new THREE.Mesh(planeGeometry, planeMaterial);
plane.receiveShadow = true;
plane.rotation.x = -0.5 * Math.PI;
plane.position.set(0, 0, 0);
scene.add(plane);
// 光源
const ambient = new THREE.AmbientLight(0x3c3c3c);
const spot = new THREE.SpotLight(0xffffff, 1.2, 150, 120);
spot.position.set(-40, 60, -10);
spot.castShadow = true;
scene.add(ambient, spot);
// 渲染器
const renderer = new THREE.WebGLRenderer();
renderer.setClearColor(0x000000);
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
// 相机控件
const orbitControl = new OrbitControls(camera, renderer.domElement);
// 性能统计
const stat = Stats();
stat.setMode(0);
// GUI界面
const controlObj = new function() {
  this.rotationSpeed = 0.02; // 旋转速度
  this.numberOfObjects = scene.children.length; // scene上的对象数量

  /**
   * 添加立方体
   */
  this.addCube = function () {
    // 构建立方体
    const cubeSize = Math.ceil(Math.random() * 3);
    const cubeGeometry = new THREE.BoxGeometry(cubeSize, cubeSize, cubeSize);
    const cubeMaterial = new THREE.MeshLambertMaterial({
      color: Math.random() * 0xffffff
    });
    const cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
    cube.castShadow = true;
    cube.name = "cube-" + scene.children.length;
    // 位置信息
    cube.position.x = -30 + Math.round(Math.random() * planeGeometry.parameters.width);
    cube.position.y = Math.round(Math.random() * 5);
    cube.position.z = -20 + Math.round(Math.random() * planeGeometry.parameters.height);

    scene.add(cube);
    this.numberOfObjects = scene.children.length;
  };

  /**
   * 删除立方体
   */
  this.removeCube = function () {
    const allChildren = scene.children;
    const last = allChildren[allChildren.length - 1];
    if (last instanceof THREE.Mesh) {
      scene.remove(last as THREE.Object3D);
      this.numberOfObjects = scene.children.length;
    }
  }

  this.outputObjects = function () {
    console.log(scene.children);
  }
};
const gui = new GUI();
// @ts-ignore
gui.add(controlObj, "addCube").name("添加立方体");
// @ts-ignore
gui.add(controlObj, "removeCube").name("删除立方体");
// @ts-ignore
gui.add(controlObj, 'rotationSpeed', 0, 0.5);
// @ts-ignore
gui.add(controlObj, 'outputObjects').name("scene.children");
// @ts-ignore
gui.add(controlObj, 'numberOfObjects').name("numberOfObjects").listen();
// 渲染函数
const render = () => {
  orbitControl.update();
  stat.update();

  scene.traverse((mesh) => {
    if (mesh instanceof THREE.Mesh && mesh !== plane) {
      mesh.rotation.x += controlObj.rotationSpeed;
      mesh.rotation.y += controlObj.rotationSpeed;
      mesh.rotation.z += controlObj.rotationSpeed;
    }
  })

  renderer.render(scene, camera);
  requestAnimationFrame(render);
};

onMounted(() => {
  canvas.value.appendChild(renderer.domElement);
  canvas.value.appendChild(stat.domElement);

  render();
});

</script>
